﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace Microsoft.VSTalk.Integration
{
    public static class VisualHelper
    {
        public static IEnumerable<UIElement> CurrentWindows()
        {
            return Application.Current.Windows.OfType<UIElement>().ToList();
        }

        public static DockPanel FindStatusBar()
        {
            var bar = SearchControls<DockPanel>("StatusBarPanel").FirstOrDefault();
            return bar;
        }

        public static IEnumerable<T> SearchControls<T>(string name = null)
        {
            var control = SearchControls(typeof(T), name);
            return control.OfType<T>();
        }

        public static T SearchParent<T>(DependencyObject startFrom) where T : class 
        {
            var control = SearchParent(typeof(T), startFrom);
            return control as T;
        }

        public static DependencyObject SearchParent(Type type, DependencyObject startFrom)
        {
            while (true)
            {
                if (startFrom == null)
                {
                    return null;
                }

                if (type.IsInstanceOfType(startFrom))
                {
                    return startFrom;
                }

                var parent = VisualTreeHelper.GetParent(startFrom);
                startFrom = parent;
            }
        }

        private static IEnumerable<DependencyObject> SearchControls(Type type, string name)
        {
            var roots = CurrentWindows();
            return roots.SelectMany(root => TraverseTree(root, o =>
            {
                if (!type.IsInstanceOfType(o))
                {
                    return false;
                }
                var fElem = o as FrameworkElement;
                if (fElem == null)
                {
                    return false;
                }
                if (string.IsNullOrEmpty(name))
                {
                    return true;
                }
                return fElem.Name == name;
            }, Enumerable.Empty<DependencyObject>())).ToList();
        }

        private static IEnumerable<DependencyObject> TraverseTree(DependencyObject current,
                Predicate<DependencyObject> predicate,
                IEnumerable<DependencyObject> agg)
        {
            if (current == null)
            {
                return agg;
            }
            if (predicate(current))
            {
                return agg.Concat(new[]
                {
                    current
                });
            }
            var count = VisualTreeHelper.GetChildrenCount(current);
            for (int i = 0; i < count; i++)
            {
                var child = VisualTreeHelper.GetChild(current, i);
                agg = TraverseTree(child, predicate, agg);
            }
            return agg;
        }

    }
}